home *** CD-ROM | disk | FTP | other *** search
- #include<stdio.h>
- #include<stdlib.h>
- #include<conio.h>
- #include<fcntl.h>
- #include<io.h>
- #include<math.h>
- #include<vsa.h>
- #include<vsa_font.h>
- #include <sys\types.h>
- #include<sys\stat.h>
-
- #ifndef _MSC_VER
- /*..... This is for Borland C Only ! .....*/
- extern unsigned _stklen = 10000;
- #endif
-
- #define FAST_RGB 0 /* Set to 1 for fast, lower quality images */
-
- /*.............................................................*/
- /* Function Prototypes go here. */
- /*.............................................................*/
- void introduction(void);
- void azure_sky(unsigned char *,int,int);
- void wipe_sky(unsigned char *,int,int);
- void shrink_city(unsigned char *,int,int);
- void merge_city(unsigned char *,int,int);
- void merge_azure(unsigned char *,unsigned char *,int,int);
- void shrink_saucer(unsigned char *,int,int);
- void merge_saucer(unsigned char *,int,int);
- void add_shadow(unsigned char *,int,int);
- void add_beam(unsigned char *,int,int);
- void get_dithered_row(int,int,unsigned char *,
- unsigned char *);
- int crack_rgb(unsigned char *,int *,int *,int *,float *,
- float *,float *);
- long read_tga_header(int,int *,int *,int *,int *);
- int write_tga_header(int,int,int,int);
- void true_color_lut(void);
- void process_step(unsigned char *,unsigned char *,
- int,int,int);
- float color_mag(float,float,float);
- float color_error(float,float,float,float,float,float);
- float hue_error(float,float,float,float,float,float);
- void bummer(char *);
- void text_update(char *,int);
- void frame(void);
- void ellipse(int,int);
- void soft_edge(unsigned char *,int,int);
-
-
- /*.............................................................*/
- /* External Parameters declared here. */
- /*.............................................................*/
- unsigned char dither[4][64]={
- {
- 1 },
- {
- 1, 3,
- 4, 2 },
- {
- 1, 9, 3, 11,
- 13, 5, 15, 7,
- 4, 12, 2, 10,
- 16, 8, 14, 6 },
- {
- 1, 33, 9, 41, 3, 35, 11, 43,
- 49, 17, 57, 25, 51, 19, 59, 27,
- 13, 45, 5, 37, 15, 47, 7, 39,
- 61, 29, 53, 21, 63, 31, 55, 23,
- 4, 36, 12, 44, 2, 34, 10, 42,
- 52, 20, 60, 28, 50, 18, 58, 26,
- 16, 48, 8, 40, 14, 46, 6, 38,
- 64, 32, 56, 24, 62, 30, 54, 22 },
- };
-
- char file_i1[9][30]={
- {""},
- {"mountain.tga"},
- {"city.tga"},
- {"wiped.tga"},
- {"withcity.tga"},
- {"saucer.tga"},
- {"withsky.tga"},
- {"withsauc.tga"},
- {"withshad.tga"},
- };
-
- char file_i2[9][30]={
- {""},
- {""},
- {""},
- {""},
- {"sky.tga"},
- {""},
- {""},
- {""},
- {""},
- };
-
- char file_o[9][30]={
- {"sky.tga"},
- {"wiped.tga"},
- {""},
- {"withcity.tga"},
- {"withsky.tga"},
- {""},
- {"withsauc.tga"},
- {"withshad.tga"},
- {"ufo.tga"},
- };
-
- unsigned char far image[16384];
- unsigned far big_image[16384];
-
- void main()
- {
- int j,width,height,type,orient;
- int file_i1_handle,file_i2_handle,file_o_handle;
- int jstrt,jend,jstep,step;
- unsigned char rgb_1[3072],rgb_2[3072];
- char text[100];
- width = 640;
- height = 480;
- orient = 0;
- introduction();
- /*.............................................................*/
- /* Set highest video resolution available. */
- /*.............................................................*/
- if(vsa_init(0x101) != 0) /* 640 x 480 x 256 */
- if(vsa_init(0x100) != 0) /* 640 x 400 x 256 */
- {
- printf("Can't set VESA video mode\n");
- printf("Is VESA BIOS Extension TSR loaded?\n");
- return;
- }
- true_color_lut();
- for(step=0;step<9;step++)
- {
- /*.............................................................*/
- /* Open the TARGA file(s) and get header info. When two files*/
- /* being opened simultaneously, they must be same type, size, */
- /* and orientation! */
- /*.............................................................*/
- if(file_i1[step][0])
- {
- if((file_i1_handle = open(file_i1[step],
- O_BINARY | O_RDONLY)) == -1)
- bummer(file_i1[step]);
- else
- if(read_tga_header(file_i1_handle,&width,
- &height,&type,&orient) == -1)
- bummer(file_i1[step]);
- }
- if(file_i2[step][0])
- {
- if((file_i2_handle = open(file_i2[step],
- O_BINARY | O_RDONLY)) == -1)
- bummer(file_i2[step]);
- else
- if(read_tga_header(file_i2_handle,&width,
- &height,&type,&orient) == -1)
- bummer(file_i2[step]);
- }
- if(file_o[step][0])
- {
- if((file_o_handle = open(file_o[step],
- O_BINARY | O_WRONLY | O_CREAT | O_TRUNC,
- S_IWRITE | S_IREAD)) == -1)
- bummer(file_o[step]);
- else
- if(write_tga_header(file_o_handle,width,
- height,orient) == -1)
- bummer(file_o[step]);
- }
- /*.............................................................*/
- /* Prepare to read out TARGA file(s). */
- /*.............................................................*/
- if(orient == 32)
- {
- jstrt = 0;
- jend = height;
- jstep = 1;
- }
- else
- {
- jstrt = height-1;
- jend = -1;
- jstep = -1;
- }
- /*.............................................................*/
- /* Do a Quicky Display of the TARGA file in file_i1, */
- /* (And remember to reset file pointer !!!) */
- /* Only do this where it makes sense (steps 1, 2, and 5). */
- /*.............................................................*/
- if((step == 1) || (step == 2) || (step == 5))
- {
- frame();
- if(file_i1[step][0])
- {
- text_update("Displaying the Input File.",252);
- for(j=jstrt;j!=jend;j+=jstep)
- {
- if(read(file_i1_handle,rgb_1,3*width) != 3*width)
- bummer(file_i1[step]);
- get_dithered_row(width,j,rgb_1,rgb_2);
- vsa_raster_line(0,width-1,j,rgb_2);
- }
- lseek(file_i1_handle,18,SEEK_SET);
- }
- }
- /*.............................................................*/
- /* Read out pixels from TARGA file(s) and process them. */
- /*.............................................................*/
- text_update("Processing, Please Wait.",252);
- frame();
- for(j=jstrt;j!=jend;j+=jstep)
- {
- if(file_i1[step][0])
- if(read(file_i1_handle,rgb_1,3*width) != 3*width)
- bummer(file_i1[step]);
- if(file_i2[step][0])
- if(read(file_i2_handle,rgb_2,3*width) != 3*width)
- bummer(file_i2[step]);
- process_step(rgb_1,rgb_2,width,j,step);
- if(file_o[step][0])
- if(write(file_o_handle,rgb_1,3*width) != 3*width)
- bummer(file_o[step]);
- }
- /*.............................................................*/
- /* If a file was opened, close it now. */
- /*.............................................................*/
- if(file_i1[step][0]) close(file_i1_handle);
- if(file_i2[step][0]) close(file_i2_handle);
- if( file_o[step][0]) close(file_o_handle);
- /*.............................................................*/
- /* Here's your chance too get out ... */
- /*.............................................................*/
- sprintf(text,"Step %d Done. Hit Any Key.",step);
- text_update(text,224);
- if(getch() == 27)
- goto BAIL;
- frame();
- }
- /*.............................................................*/
- /* Program is over, return display to standard text mode. */
- /*.............................................................*/
- BAIL:
- vsa_init(0x3);
- return;
- }
-
- void process_step(unsigned char *rgb_1,unsigned char *rgb_2,
- int width,int j,int step)
- {
- switch(step)
- {
- case 0:
- azure_sky(rgb_1,width,j);
- break;
- case 1:
- wipe_sky(rgb_1,width,j);
- break;
- case 2:
- shrink_city(rgb_1,width,j);
- break;
- case 3:
- merge_city(rgb_1,width,j);
- break;
- case 4:
- merge_azure(rgb_1,rgb_2,width,j);
- break;
- case 5:
- shrink_saucer(rgb_1,width,j);
- break;
- case 6:
- merge_saucer(rgb_1,width,j);
- break;
- case 7:
- add_shadow(rgb_1,width,j);
- break;
- case 8:
- add_beam(rgb_1,width,j);
- break;
- default: break;
- }
- return;
- } /*.... END process_step .....*/
-
-
- /*........................ AZURE_SKY ..........................*/
- /* This routine generates a blue, blue-green gradient much */
- /* like the crisp blue skies of Montana. (Never been there, */
- /* seen pictures). (The data is displayed as its generated). */
- /*.............................................................*/
- void azure_sky(unsigned char *rgb_1,int width,int j)
- {
- unsigned char array[1024];
- int i;
- for(i=0;i<width;i++)
- {
- rgb_1[3*i+2] = 0;
- rgb_1[3*i+1] = 64+j/2.53;
- rgb_1[3*i+0] = 128+j/3.75;
- }
- get_dithered_row(width,j,rgb_1,array);
- vsa_raster_line(0,width-1,j,array);
- return;
- } /*.... END azure_sky .....*/
-
-
- /*......................... WIPE_SKY ..........................*/
- /* This routine is customized to work specifically with the */
- /* MOUNTAIN.TGA picture. It goes in and zeros out the sky to */
- /* prepare MOUNTAIN.TGA for the next step. */
- /* This routine makes use of a hue test and a color test */
- /* to determine which pixels make up the sky. The hue test */
- /* finds similar hues independent of brightness while the */
- /* color test finds similar colors in the absolute sense. */
- /*.............................................................*/
- void wipe_sky(unsigned char *rgb_1,int width,int j)
- {
- unsigned char array[1024];
- int i;
- float h_error,c_error;
- for(i=0;i<width;i++)
- {
- h_error = hue_error(rgb_1[3*i+2],rgb_1[3*i+1],
- rgb_1[3*i+0],0.62,0.54,0.58);
- c_error = color_error(rgb_1[3*i+2],rgb_1[3*i+1],
- rgb_1[3*i+0],140,122,131);
- if((h_error < 0.03) && (c_error < 17))
- {
- rgb_1[3*i+2] = 0;
- rgb_1[3*i+1] = 0;
- rgb_1[3*i+0] = 0;
- }
- }
- get_dithered_row(width,j,rgb_1,array);
- vsa_raster_line(0,width-1,j,array);
- return;
- } /*.... END wipe_sky .....*/
-
-
- /*......................... SHRINK_CITY .......................*/
- /* This routine is customized to work specifically with the */
- /* CITY.TGA picture. It extracts the city within a window */
- /* and shrinks it by a factor of 3 in x and y. Then the */
- /* resulting image is placed in the external 'image' array */
- /* and also displayed on the screen. */
- /*.............................................................*/
- void shrink_city(unsigned char *rgb_1,int width,int j)
- {
- int i,n,q,red,grn,blu;
- unsigned char array[1024];
- /*.............................................................*/
- /* Put up a gray box where reduced city will be drawn. */
- /* Only draw it once, just before city shrinking starts. */
- /*.............................................................*/
- if(j == 479)
- {
- vsa_set_color(0x49);
- vsa_move_to(242,331);
- vsa_rect_fill(356,406);
- }
- /*.............................................................*/
- /* Bail out unless you're within the extract region of the */
- /* image and you're on every 3rd row. */
- /*.............................................................*/
- if((j < 60) || (j > 290))
- return;
- if((((float)j/3.0)-j/3) != 0)
- return;
- /*.............................................................*/
- /* Extract city within rectangle 115,60 to 460,290 and reduce */
- /* size by a factor of 3 by simple undersampling of image and */
- /* convert extracted pixels to grayscale. Store in image array*/
- /* Then display reduced city in little window. */
- /*.............................................................*/
- n = ((j-60)/3)*115;
- q=j/3+310;
- for(i=115;i<460;i+=3)
- {
- red = rgb_1[3*i+2];
- grn = rgb_1[3*i+1];
- blu = rgb_1[3*i+0];
- image[n] = (red + grn + blu)/3;
- rgb_1[i+2] = image[n];
- rgb_1[i+1] = image[n];
- rgb_1[i+0] = image[n];
- n++;
- }
- get_dithered_row(width,q,rgb_1+115,array);
- vsa_raster_line(242,356,q,array);
- return;
- } /*.... END shrink_city .....*/
-
- /*.......................... MERGE_CITY .......................*/
- /* This routine takes the reduced city in the 'image' array */
- /* and inserts it into the WIPED.TGA image replacing only */
- /* those pixels which are equal to zero. */
- /*.............................................................*/
- void merge_city(unsigned char *rgb_1,int width,int j)
- {
- int i,n;
- unsigned char array[1024];
- /*.............................................................*/
- /* Composite the city in the 'image' array with the WIPED */
- /* mountain scene within rectangle (523,214) to (637,289). */
- /* Also display results. */
- /*.............................................................*/
- for(i=0;i<width-1;i++)
- {
- if((j >= 214) && (j <= 289))
- if((i>=523) && (i < 637))
- if((rgb_1[3*i+2] | rgb_1[3*i+1] | rgb_1[3*i+0]) == 0)
- {
- n=i-523 + (j-214)*115;
- rgb_1[3*i+2] = image[n];
- rgb_1[3*i+1] = image[n];
- rgb_1[3*i+0] = image[n];
- }
- }
- get_dithered_row(width,j,rgb_1,array);
- vsa_raster_line(0,width-1,j,array);
- return;
- } /*.... END merge_city .....*/
-
-
- /*.......................... MERGE_AZURE ......................*/
- /* This routine takes the azure sky in SKY.TGA and uses its */
- /* data to replace all zero value pixels in the previous */
- /* image WITHCITY.TGA. */
- /*.............................................................*/
- void merge_azure(unsigned char *rgb_1,unsigned char *rgb_2,
- int width,int j)
- {
- unsigned char array[1024];
- int i;
- for(i=0;i<width;i++)
- {
- if((rgb_1[3*i+2] | rgb_1[3*i+1] | rgb_1[3*i+0]) == 0)
- {
- rgb_1[3*i+2] = rgb_2[3*i+2];
- rgb_1[3*i+1] = rgb_2[3*i+1];
- rgb_1[3*i+0] = rgb_2[3*i+0];
- }
- }
- get_dithered_row(width,j,rgb_1,array);
- vsa_raster_line(0,width-1,j,array);
- return;
- } /*.... END merge_azure .....*/
-
-
- /*......................... SHRINK_SAUCER .....................*/
- /* This routine is customized to work specifically with the */
- /* SAUCER.TGA picture. It extracts the saucer within a window*/
- /* and shrinks it by a factor of 2.5 in x and y. Then the */
- /* resulting image is placed in the external 'image' array */
- /* and also displayed on the screen. */
- /*.............................................................*/
- void shrink_saucer(unsigned char *rgb_1,int width,int j)
- {
- int i,n,p,q,red,grn,blu;
- float x;
- unsigned char array[1024];
- /*.............................................................*/
- /* Put up a gray box where reduced saucer will be drawn. */
- /* Only draw it once, just before saucer shrinking starts. */
- /*.............................................................*/
- if(j == 479)
- {
- vsa_set_color(0x49);
- vsa_move_to(235,310);
- vsa_rect_fill(414,379);
- }
- /*.............................................................*/
- /* Bail out unless you're within the extract region of the */
- /* image and you're on every 2.5th row. */
- /*.............................................................*/
- if((j < 125) || (j > 298))
- return;
- if((int)(j/2.5) == (int)((j-1)/2.5))
- return;
- /*.............................................................*/
- /* Extract saucer within rectangle 100,125 to 550,300 and */
- /* reduce size by a factor of 2.5 by simple undersampling of */
- /* image and convert extracted pixels to grayscale. Store in */
- /* 'image' array and also dither and display on screen. */
- /*.............................................................*/
- n=180*(int)((j-125)/2.5);
- p=0;
- q=j/2.5+260;
- for(x=100;x<550;x+=2.5)
- {
- i = x+0.5;
- red = rgb_1[3*i+2];
- grn = rgb_1[3*i+1];
- blu = rgb_1[3*i+0];
- image[n] = (red + grn + blu)/3;
- rgb_1[p+2] = image[n];
- rgb_1[p+1] = image[n];
- rgb_1[p+0] = image[n];
- n++;
- p+=3;
- }
- get_dithered_row(width,q,rgb_1,array);
- vsa_raster_line(235,414,q,array);
- return;
- } /*.... END shrink_saucer .....*/
-
-
- /*.......................... MERGE_SAUCER .....................*/
- /* This routine takes the reduced saucer in the 'image' array */
- /* and inserts it into the WITHSKY.TGA image. The replacement*/
- /* decision is based on a test of the pixel's blue component */
- /* in the WITHSKY.TGA picture. */
- /*.............................................................*/
- void merge_saucer(unsigned char *rgb_1,int width,int j)
- {
- int i,n;
- unsigned char array[1024];
- /*.............................................................*/
- /* Composite the saucer in the image array with the modified */
- /* mountain scene within the rectangle defined by (203,25) */
- /* and (382,94). Use a modified "replace if brighter" test. */
- /* Specifically, replace if saucer pixel is greater than 1/3 */
- /* of existing pixels blue component. (nothing magical here, */
- /* this scheme was found by experimenting). */
- /*.............................................................*/
- n = (j-25)*180;
- for(i=0;i<width-1;i++)
- {
- if((j >= 25) && (j <= 94))
- if((i >= 203) && (i <= 382))
- {
- if(image[n] >= (rgb_1[3*i+0]/3))
- {
- rgb_1[3*i+2] = image[n];
- rgb_1[3*i+1] = image[n];
- rgb_1[3*i+0] = image[n];
- }
- n++;
- }
- }
- get_dithered_row(width,j,rgb_1,array);
- vsa_raster_line(0,width-1,j,array);
- return;
- } /*.... END merge_saucer .....*/
-
-
- /*........................ ADD_SHADOW .........................*/
- /* This routine generates an ellipse and then composits it */
- /* with the WITHSAUC.TGA picture using a subtractive */
- /* technique. The ellipse serves as a mask which causes a */
- /* 30% reduction of pixel intensity for masked pixels. */
- /*.............................................................*/
- void add_shadow(unsigned char *rgb_1,int width,int j)
- {
- int i,n;
- unsigned char array[1024];
- float scale;
- /*.............................................................*/
- /* Generate an ellipse mask in the 'image' array once before */
- /* getting to overlay region. */
- /*.............................................................*/
- if(j==479)
- ellipse(180,35);
- /*.............................................................*/
- /* Composite the shadow disk region (75,310) (254,344). */
- /*.............................................................*/
- n = (j-310)*180;
- for(i=0;i<width-1;i++)
- {
- if((j >= 310) && (j <= 344))
- if((i >= 75) && (i <= 254))
- {
- scale = (255.0 - 0.4*image[n])/255.0;
- rgb_1[3*i+2] = rgb_1[3*i+2]*scale;
- rgb_1[3*i+1] = rgb_1[3*i+1]*scale;
- rgb_1[3*i+0] = rgb_1[3*i+0]*scale;
- n++;
- }
- }
- get_dithered_row(width,j,rgb_1,array);
- vsa_raster_line(0,width-1,j,array);
- return;
- } /*.... END add_shadow .....*/
-
-
- /*........................ ADD_BEAM ...........................*/
- /* This routine generates a Transporter Beam (the standard */
- /* issue) and composits it with the WITHSHAD.TGA picture */
- /* using an additive technique. The beam has a sinusoidal */
- /* intensity cross section and is capped with an ellipse. */
- /*.............................................................*/
- void add_beam(unsigned char *rgb_1,int width,int j)
- {
- int i,n,red,grn,boost;
- unsigned char array[1024];
- float taps[40];
- /*.............................................................*/
- /* Generate an ellipse mask in the 'image' array once before */
- /* getting to overlay region. Also precompute the */
- /* sinusoidal beam profile. */
- /*.............................................................*/
- if(j==479)
- {
- ellipse(40,22);
- for(i=0;i<40;i++)
- taps[i] = sin(0.0785*(float)i);
- }
- /*.............................................................*/
- /* Use an additive mixing technique to composite the beam */
- /* (me up scotty) into the image. Beam fills rectangle with */
- /* coordinates (273,88) to (312,320). */
- /*.............................................................*/
- n = (j-294)*40;
- for(i=0;i<width-1;i++)
- {
- if((j >= 88) && (j <= 304))
- if((i >= 273) && (i <= 312))
- {
- boost = 75.0*taps[i-273];
- red = rgb_1[3*i+2] + boost;
- grn = rgb_1[3*i+1] + boost;
- rgb_1[3*i+2] = min(red,255);
- rgb_1[3*i+1] = min(grn,255);
- }
-
- /*.... Cap the beam with half of an ellipse. ...*/
- if((j >= 305) && (j <= 315))
- if((i >= 273) && (i <= 312))
- {
- boost = (75.0*taps[i-273]*image[n])/255.0;
- red = rgb_1[3*i+2] + boost;
- grn = rgb_1[3*i+1] + boost;
- rgb_1[3*i+2] = min(red,255);
- rgb_1[3*i+1] = min(grn,255);
- n++;
- }
- }
- get_dithered_row(width,j,rgb_1,array);
- vsa_raster_line(0,width-1,j,array);
- return;
- } /*.... END add_beam .....*/
-
-
- /*....................... READ_TGA_HEADER ....... 5-17-94 ....*/
- /* This routine parses through a TGA header and returns the */
- /* file offset in bytes to the first byte of pixel data. */
- /* It also returns image width, height, and type (type 2 is the*/
- /* uncompressed 24 bit image type). */
- /*.............................................................*/
- long read_tga_header(int handle, int *width,
- int *height, int *type,
- int *orientation)
- {
- unsigned long offset;
- unsigned char buff[18];
- if(read(handle,buff,18) != 18)
- return -1;
- offset = 18+buff[0];
- *type = buff[2];
-
- *width = *((unsigned *)buff + 6);
- *height = *((unsigned *)buff + 7);
- *orientation = buff[17];
- return offset;
- } /*.... END read_tga_header .....*/
-
-
- /*....................... WRITE_TGA_HEADER ....... 7-5-94 ....*/
- /* This routine writes a TGA header: 24 bit true color image */
- /*.............................................................*/
- int write_tga_header(int handle, int width,int height,
- int orientation)
- {
- int error = 0;
- unsigned char buff[18];
- buff[0] = 0;
- buff[1] = 0;
- buff[2] = 2;
- buff[3] = 0;
- buff[4] = 0;
- buff[5] = 0;
- buff[6] = 0;
- buff[7] = 0;
- buff[8] = 0;
- *((unsigned *)buff + 4) = 0;
- *((unsigned *)buff + 5) = 0;
- *((unsigned *)buff + 6) = width;
- *((unsigned *)buff + 7) = height;
- buff[16] = 24;
- buff[17] = orientation;
- if(write(handle,buff,18) != 18)
- error = -1;
- return error;
- } /*.... END write_tga_header .....* /
-
-
- /*.................... GET_DITHERED_ROW ......... 7-15-94 .....*/
- /* This routine computes the dithered pixel color for all of */
- /* pixels in a row in the array 'rgb' and stores the results */
- /* in the array 'pixels'. The row is 'width' wide and starts at*/
- /* screen row address 'j'. The 'rgb' array is a 24 bit color */
- /* array with every 3 bytes defining a new pixel. The */
- /* resulting 'pixels' array defines each pixel as an 8 bit RGB */
- /* pixel (one byte per pixel). */
- /*.............................................................*/
- void get_dithered_row(int width,int j,unsigned char *rgb,
- unsigned char *pixels)
- {
- int i,n,m,q,r,red_lvl,grn_lvl,blu_lvl,size,size_sqr;
- int red_boost,grn_boost,blu_boost;
- float x,y,frl,fgl,fbl;
- size = 8;
- size_sqr = 64;
- q = 3;
- /*.... If FAST_RGB = 1, don't dither, do fast 8 bit RGB. ....*/
- if(FAST_RGB)
- {
- for(i=0;i<width;i++)
- {
- pixels[i] = (rgb[3*i+2] & 0xe0) +
- ((rgb[3*i+1] & 0xe0) >> 3) +
- (rgb[3*i+0] >> 6);
- }
- return;
- }
- y = (float)j/size;
- n = (int)(size*(y - (int)y) + 0.5);
- for(i=0;i<width;i++)
- {
- /*.............................................................*/
- /* For the pixels screen address i,j, compute pixel address r */
- /* within the dither box. Also select dither box q based on */
- /* size (size = 1, 2, 4, or 8) (q = 0, 1, 2, or 3). */
- /*.............................................................*/
- x = (float)i/size;
- m = (int)(size*(x - (int)x) + 0.5);
- r = m+n*size;
- /*.............................................................*/
- /* Get the Dark Pixel color, the Light Pixel components, and */
- /* the pixel color errors. */
- /*.............................................................*/
- pixels[i] = crack_rgb(rgb+3*i,&red_boost,&grn_boost,
- &blu_boost,&frl,&fgl,&fbl);
- /*.............................................................*/
- /*Scale the pixel color error values based on dither box size */
- /*.............................................................*/
- red_lvl = size_sqr*frl;
- grn_lvl = size_sqr*fgl;
- blu_lvl = size_sqr*fbl;
- /*.............................................................*/
- /*Test the pixels red, green, and blue error values against the*/
- /*thresholds in the dither box. Decide which color to use. */
- /*.............................................................*/
- if(dither[q][r] <= red_lvl) /*Boost Red*/
- pixels[i] = (pixels[i] & 0x1f)+(red_boost<<5);
- if(dither[q][r] <= grn_lvl) /*Boost Grn*/
- pixels[i] = (pixels[i] & 0xe3)+(grn_boost<<2);
- if(dither[q][r] <= blu_lvl) /*Boost Blu*/
- pixels[i] = (pixels[i] & 0xfc)+blu_boost;
- }
- return;
- } /*.... END get_dithered_row ....*/
-
-
-
- /*.......................... CRACK_RGB ........... 5-27-94 ....*/
- /* This routine takes the 24 bit RGB color value in the 'rgb' */
- /* array, quantizes it down to an 8 bit color value (3 bit red,*/
- /* 3 bit green, and 2 bit blue) and returns this 8 bit */
- /* 'base_color' value. It also computes the 8 bit color boost */
- /* values '*red_boost', 'grn_boost', and 'blu_boost' which are */
- /* used to draw dithered pixels. It also computes the color */
- /* error values 'red_lvl', 'grn_lvl', and 'blu_lvl' which */
- /* determine when the dither function draws with 'base_color' */
- /* and when it draws with 'xxx_boost' color. */
- /*.............................................................*/
- int crack_rgb(unsigned char *rgb,int *red_boost,int *grn_boost,
- int *blu_boost,float *red_lvl,float *grn_lvl,
- float *blu_lvl)
- {
- int base_color,red,grn,blu;
- float fred,fgrn,fblu;
-
- fred = rgb[2]/36.6; /*36.6 = (256 shades of red)/(2^3 - 1) */
- fgrn = rgb[1]/36.6; /*36.6 = (256 shades of grn)/(2^3 - 1) */
- fblu = rgb[0]/85.4; /*85.4 = (256 shades of blu)/(2^2 - 1) */
-
- red = fred;
- grn = fgrn;
- blu = fblu;
- base_color = (red << 5)+(grn << 2)+blu; /*Dark Pixel color */
-
- *red_lvl = fred - red;
- *grn_lvl = fgrn - grn;
- *blu_lvl = fblu - blu;
-
- *red_boost = red+1; /*This is the Light Pixel color for red */
- *grn_boost = grn+1; /*This is the Light Pixel color for grn */
- *blu_boost = blu+1; /*This is the Light Pixel color for blu */
-
- return base_color;
- } /*.... END crack_rgb .....*/
-
-
- /*.................... TRUE_COLOR_LUT.C .......... 5-15-94 ....*/
- /* This routine generates a 'true color' LUT. An 8 bit index */
- /* into the LUT represents 3 bits of RED, 3 bits of GREEN, and */
- /* 2 bits of BLUE. The 3 msbs of the 8 bit index are the RED */
- /* field, next 3 are GREEN, and the 2 lsbs are the BLUE field. */
- /* */
- /*.............................................................*/
- void true_color_lut(void)
- {
- int i;
- unsigned char color_array[768];
- for(i=0;i<256;i++)
- {
- color_array[3*i+0]= ((i & 0x00e0) >> 5) * 9;
- color_array[3*i+1]= ((i & 0x001c) >> 2) * 9;
- color_array[3*i+2]= (i & 0x0003) * 21;
- }
- vsa_write_color_block(0,256,color_array);
- return;
- } /*..... End true_color_lut .....*/
-
-
- /*.................... COLOR_MAG .............. 7-15-94 .......*/
- /* This routine takes an RGB color defined by 'r', 'g', and */
- /* 'b' and returns the absolute magnitude (brightness) of the */
- /* color. */
- /*.............................................................*/
- float color_mag(float r,float g,float b)
- {
- return sqrt(r*r+g*g+b*b);
- } /*..... End color_mag .....*/
-
-
- /*.................... COLOR_ERROR ............ 7-15-94 .......*/
- /* This routine takes two RGB colors defined by 'r0', 'g0', */
- /* 'b0' and 'r1', 'g1', 'b1' and returns the distance between */
- /* the two colors in RGB color space. */
- /*.............................................................*/
- float color_error(float r0,float g0,float b0,
- float r1,float g1,float b1)
- {
- float dr,dg,db;
- dr = (r0-r1);
- dg = (g0-g1);
- db = (b0-b1);
- return sqrt(dr*dr+dg*dg+db*db);
- } /*..... End color_error .....*/
-
-
- /*.................... HUE_ERROR .............. 7-15-94 .......*/
- /* This routine compares the RGB color defined by 'r,g,b' to */
- /* the color HUE defined by 'ur,ug,ub' and returns the distance*/
- /* between the RGB color and the HUE. The distance ranges */
- /* from 0 to square root of 3 (1.73...) */
- /* NOTE: 'ur,ug,ub' is a "Unit Vector" and */
- /* sqrt(ur*ur + ug*ug + ub*ub) must equal 1.0. */
- /*.............................................................*/
- float hue_error(float r,float g,float b,
- float ur,float ug,float ub)
- {
- float dr,dg,db,mag;
- mag = color_mag(r,g,b);
- if(mag == 0) mag = 1.0;
- dr = (r/mag-ur);
- dg = (g/mag-ug);
- db = (b/mag-ub);
- return sqrt(dr*dr+dg*dg+db*db);
- } /*..... End hue_error .....*/
-
-
- /*.......................... BUMMER ...........................*/
- /* This routine prints a file error message. You give */
- /* it the name of the file for the message in 'filename'. */
- /*.............................................................*/
- void bummer(char *filename)
- {
- char text[100];
- sprintf(text,
- "File Access Error! Filename = '%s'",filename);
- vsa_write_string(0,YResolution-2*YCharSize,224,text);
- vsa_write_string(0,YResolution-1*YCharSize,224,
- "Hit Any Key ...");
- getch();
- vsa_init(3);
- exit(1);
- } /*..... End bummer .....*/
-
-
- /*......................... TEXT_UPDATE .......................*/
- /* This routine prints the text string in 'text' out to the */
- /* screen in 'color'. It does this at the bottom center of a */
- /* 640 x 480 screen by first clearing out the last printed */
- /* message. */
- /*.............................................................*/
- void text_update(char *text,int color)
- {
- vsa_set_text_scale(1.2,1.2);
- vsa_set_color(0);
- vsa_move_to(200,475-YCharSize-1);
- vsa_rect_fill(460,475);
- vsa_write_string(205,475-YCharSize,color,text);
- return;
- } /*..... End text_update .....*/
-
-
- /*............................. FRAME .........................*/
- /* This routine draws a frame around the 640 x 480 screen. */
- /* The reason I do this is so that you can tell when an image */
- /* is being redrawn (the frame slowly gets eaten up). */
- /*.............................................................*/
- void frame(void)
- {
- vsa_set_color(255);
- vsa_move_to(0,0);
- vsa_rect(639,479);
- vsa_set_color(0);
- vsa_move_to(1,1);
- vsa_rect(638,478);
- vsa_set_color(255);
- vsa_move_to(2,2);
- vsa_rect(637,477);
- vsa_set_color(0);
- vsa_move_to(3,3);
- vsa_rect(636,476);
- return;
- } /*..... End frame .....*/
-
-
- /*......................... ELLIPSE .............. 7-22-94 ....*/
- /* This routine generates a filled ellipse mask into the */
- /* global 'image array. The ellipse has width of 'dx' and */
- /* height of 'dy'. The equation for this ellipse is: */
- /* */
- /* x^2 + y^2 */
- /* -------- -------- = 1 */
- /* (dx/2)^2 (dy/2)^2 */
- /* */
- /* The 'image' array values are 0 outside of the ellipse and */
- /* 255 inside the ellipse. The ellipse has a soft edge with */
- /* 'image' values between 0 and 255. The soft edge is */
- /* achieved by a 3x3 pixel averaging operation via the */
- /* 'soft_edge' function. */
- /* */
- /* NOTE: The 'image' array must be large enough to hold all of */
- /* this data (image will be dx wide and dy high). */
- /*.............................................................*/
- void ellipse(int dx,int dy)
- {
- int i,j,m,n;
- float rx,ry;
- /*.............................................................*/
- /* Clear out the image array before writing in ellipse mask. */
- /*.............................................................*/
- for(n=0;n<dy;n++)
- for(m=0;m<dx;m++)
- image[m+n*dx] = 0;
- /*.............................................................*/
- /* Now compute ellipse and draw its mask into image array. */
- /*.............................................................*/
- rx = (dx-1)/2.0;
- ry = (dy-1)/2.0;
- for(j=-ry ; j<=+ry ; j++)
- {
- i = sqrt(rx*rx*(1 - (j*j)/(ry*ry)));
- for(m=-i;m<=i;m++)
- {
- n = m+rx+(j+(int)ry)*dx;
- image[n] = 255;
- }
- }
- soft_edge(image,dx,dy);
- return;
- } /*..... End ellipse .....*/
-
-
- void introduction(void)
- {
- printf("This program goes through the evolution of mild\n");
- printf("mannered MOUNTAIN.TGA to the ultimate UFO sighting\n");
- printf("UFO.TGA. Before you run this program, You must\n");
- printf("have the following three files in the current\n");
- printf("directory:\n");
- printf(" MOUNTAIN.TGA\n");
- printf(" CITY.TGA\n");
- printf(" SAUCER.TGA\n");
- printf("\n");
- printf("Furthermore, you need an additional 7 Mbytes\n");
- printf("of hard disk space available since the following\n");
- printf("intermediate TARGA image files are created:\n");
- printf("\n");
- printf(" SKY.TGA\n");
- printf(" WIPED.TGA\n");
- printf(" WITHCITY.TGA\n");
- printf(" WITHSKY.TGA\n");
- printf(" WITHSAUC.TGA\n");
- printf(" WITHSHAD.TGA\n");
- printf(" UFO.TGA (This is the final image)\n");
- printf("\n");
- printf("Hit any key to continue, ESC to quit.\n");
- if(getch() == 27)
- exit(1);
- return;
- }
-
- void soft_edge(unsigned char *image,int width,int height)
- {
- int i,j,m,n,q,x,y;
- /*.............................................................*/
- /* First clear out the temporary array. */
- /*.............................................................*/
- for(i=0;i<width*height;i++)
- big_image[i] = 0;
- /*.............................................................*/
- /* Now, for each pixel in 'image' array, do a 3x3 pixel */
- /* average. */
- /*.............................................................*/
- for(j=0;j<height;j++)
- for(i=0;i<width;i++)
- {
- q = i+j*width;
- for(n=0;n<3;n++)
- for(m=0;m<3;m++)
- {
- x = i+m-1;
- y = j+n-1;
- if((y >= 0) && (y < height))
- if((x >= 0) && (x < width))
- big_image[q] += image[x+y*width];
- }
- big_image[q] = big_image[q]/9;
- }
- /*.............................................................*/
- /* Finally, transfer results back to the 'image' array. */
- /*.............................................................*/
- for(i=0;i<width*height;i++)
- image[i] = big_image[i];
- return;
- }
-